<!--
 * @Author: yangzhiyu yangzhiyu@mail.pigcms.com
 * @Date: 2024-03-29 16:56:47
 * @LastEditors: yangzhiyu yangzhiyu@mail.pigcms.com
 * @LastEditTime: 2024-04-01 16:27:39
 * @FilePath: \fe_user_pc\src\views\shotstack\MuseMixedCut\MixedCutPreview\components\saveVideoDialog.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
   音色选择
-->
<script setup>
import baseModel from "@/components/baseModel/baseModel.vue";
import { computed, onMounted, reactive, ref, nextTick, watch } from "vue";
import request from "@/common/utils/request";

// icon
import {
  CaretRightOutlined,
  PauseOutlined,
  RedoOutlined,
  QuestionCircleOutlined,
} from "@ant-design/icons-vue";
import { message } from "ant-design-vue";

// 仓库
import { useStore } from "vuex";
import { random } from "nanoid";
import { nanoid } from "nanoid";

import auditionDialog from "./dialog/auditionDialog.vue";

const store = useStore();

// 仓库中的 本项抽屉数据
// const currentIndex = computed(() => store.state.currentIndex);
const Global_tts_config = computed(() => {
  return store.state.shotstack.Global_tts_config.configs.find(
    (ele) => ele.tab_id == "text"
  );
});

// 当前tabs 选择的项
const activeKey = ref("common");

// 仓库提交
const setStore = (data) => {
  store.commit("MODIFY_GLOSUBTITLES_TTSCONFIG", data);
};

// 收集数据
let state = reactive({
  speed: 0, // 语速
  volume: 6, // 音量
  emotion_category: "neutral", // 预期情感类型
  emotion_intensity: 50, //情感程度
  img: "https://local.kuaijingai.com/public_web/static/images/workAi/voice/icon-women.png",
  name: "智聆",
  selectVoice: [], // 勾选的声音id
});

const voiceData = reactive({
  //  tab栏
  category: [],
  // 音色列表
  list: [],
});

// 语气列表
const toneList = ref([]);

// 选择的音色
const selectVoices = ref([]);

// 是否开启随机
const isRandom = ref(true);

// 获取场景数据
const getVoiceData = async () => {
  const res = await request.get("/work_ai", "/user/shotstack/voice/category");
  voiceData.category = res.result;
  console.log(res, "场景列表");
  getVoiceList();
};

// 获取音色列表
const getVoiceList = async () => {
  const res = await request.get("/work_ai", "/user/shotstack/voice/list", {
    category: activeKey.value,
  });
  if (res.result.length > 0) {
    console.log(res, "音色列表");
    res.result.forEach((element) => {
      element.id = nanoid();
    });
    voiceData.list = res.result;
    console.log(voiceData.list);
    toneList.value = res.result[0].item[0]?.emotion_style || [];
    state.emotion_category = toneList.value?.[0]?.key || "neutral";
  }
};

// 音频播放器
const audioRef = ref(null);
const voiceUrl = ref(null);
// 播放声音
const playFlage = ref(true); // false , 显示试听
const playitem = ref(null); // 存放当期那预览声音的id
const loding = ref(false);
const playVoice = (item) => {
  // playFlage.value = !playFlage.value
  // 相同 , 并且正在播放, 暂停
  if (playitem.value == item.id) {
    playFlage.value ? audioRef.value.pause() : audioRef.value.play();
    // playFlage.value = false
    playFlage.value = !playFlage.value;
  } else {
    // 不同或首次播放
    playitem.value = item.id;
    playFlage.value = true;
    loding.value = true;
    voiceUrl.value = item.voice_url;
    console.log(voiceUrl.value);
    nextTick(() => {
      audioRef.value.play();
      loding.value = false;
    });
  }
};

// 判断是否显示正在播放状态
const playState = (id) => {
  if (playitem.value !== id) return false;
  if (playFlage.value) {
    return true;
  } else {
    return false;
  }
};

// 播放结束
const handleAudioEnded = () => {
  playFlage.value = false;
  audioRef.value.currentTime = 0;
};

// 全局音色试听
// 单个音色进行自定义试听
const auditionVoice = ref({
  timbre_id: "",
  name: "",
});
const globalAudio = ref(null);
const globalPlay = ref(false); // false - 暂停 显示播放
const globalAudioUrl = ref("");
// 全局试听播放结束
const handleGlobalAudioEnded = () => {
  globalAudio.value.currentTime = 0;
  globalPlay.value = false;
  console.log("调用了", globalPlay.value);
};

/**
 * 文案试听
 */

const audition = ref("");

//  按钮是否加载中
const btnLoding = ref(false);
const paramsData = computed(() => {
  return {
    text: audition.value,
    speed: state.speed,
    timbre_id: auditionVoice.value?.timbre_id || null,
    volume: state.volume,
    emotion_category: state.emotion_category,
    emotion_intensity: state.emotion_intensity,
  };
});
const isChange = ref(false);
watch(
  () => paramsData.value,
  (nv, ov) => {
    isChange.value = true;
  },
  {
    deep: true,
  }
);

const auditionDialogRef = ref(null);

const updateAudition = (data) => {
  auditionVoice.value = {
    timbre_id: data?.tone_id || "",
    name: data?.name || "",
  };
  playRun();
};

// 点击播放按钮
const auditionPlay = () => {
  if (!audition.value.trim()) return message.warn("请输入文案");
  if (!auditionVoice.value?.timbre_id) {
    message.success("请选择想要试听的音色");
    auditionDialogRef.value.showModal(selectVoices.value);
    return;
  }
  playRun();
};

// 重置当前试听的数据
const resetAudition = () => {
  auditionVoice.value.name = "";
  auditionVoice.value.timbre_id = "";
  message.success("试听音色已重置");
};

// 试听
const playRun = () => {
  if (!isChange.value && globalAudioUrl.value && globalPlay.value) {
    // 数据无变化, 有url 播放中 => 暂停
    globalAudio.value.pause();
    globalPlay.value = false;
    return;
  } else if (!isChange.value && globalAudioUrl.value && !globalPlay.value) {
    // 数据无变化 , 有url 暂停中 => 播放
    globalAudio.value.play();
    globalPlay.value = true;
    return;
  }
  btnLoding.value = true;
  request
    .get("/work_ai", "/user/shotstack/textToVoice", paramsData.value)
    .then((res) => {
      let tiem = setInterval(() => {
        request
          .get("/work_ai", "/user/shotstack/getVoice", {
            task_id: res.result.task_id,
            request_id: res.result.request_id || "",
          })
          .then((task) => {
            if (task.result.Data.ResultUrl) {
              console.log(task, "获取的音频");
              clearInterval(tiem);
              voiceUrl.value = task.result.Data.ResultUrl;
              btnLoding.value = false;
              globalAudioUrl.value = task.result.Data.ResultUrl;
              isChange.value = false;
              nextTick(() => {
                globalAudio.value && globalAudio.value.play();
                globalPlay.value = true;
              });
            }
          });
      }, 1000);
    });
};

// 判断右侧音量重置按钮 是否展示
const resetShow = computed(() => {
  return state.emotion_intensity == 1 && state.speed == 1 && state.volume == 1;
});

const tabsChange = (activeKey) => {
  getVoiceList();
};

const dialog = ref(null);

// 选择某项卡片
const selectCart = (item) => {
  if (isRandom.value) return;
  let index = selectVoices.value.findIndex((i) => i.tone_id == item.timbre_id);
  if (index > -1) {
    selectVoices.value.splice(index, 1);
    return;
  } else {
    selectVoices.value.push({
      tone_id: item.timbre_id,
      name: item.name,
      img: item.img,
      audio_url: item.voice_url,
      volume: 10,
      speed: state.speed,
      emotion_category: state.emotion_category,
      emotion_intensity: state.emotion_intensity,
      human_style: item.human_style,
    });
  }
  // state.selectVoice.push = item.timbre_id;
  // state.name = item.name;
  // state.img = item.img;
};

// 卡片判断是否被选中
const isSelect = (item) => {
  let index = selectVoices.value.findIndex((i) => i.tone_id == item.timbre_id);
  return index > -1;
};

const showModal = () => {
  // debugger
  Object.assign(state, {
    speed: Global_tts_config.value.speed, // 语速
    volume: Global_tts_config.value.volume, // 音量
    tone_id: Global_tts_config.value.tone_id, // 选择的声音id
    emotion_category: Global_tts_config.value.emotion_category, // 预期情感类型
    emotion_intensity: Global_tts_config.value.emotion_intensity, //情感程度
    img: Global_tts_config.value.img, // 展示图片地址
    name: Global_tts_config.value.name, // 音色名称
    // isRandom: Global_tts_config.value.isRandom, // 是否开启随机声音
    selectVoice: JSON.parse(
      JSON.stringify(Global_tts_config.value?.selectVoice || [])
    ), // 多选音色数组
  });

  // 是否随机
  isRandom.value = store.state.shotstack.Global_tts_config.isRandom;

  // 暂存id 赋值
  console.log(Global_tts_config.value, "本地数据");
  selectVoices.value = JSON.parse(
    JSON.stringify(Global_tts_config.value?.selectVoice || [])
  );
  // if (
  //   Global_tts_config.value?.selectVoice &&
  //   Global_tts_config.value.selectVoice.length > 0
  // ) {
  // }
  getVoiceData();

  dialog.value.showModal();
};

// 获取一个随机项
const getRandomItem = (data) => {
  // 随机选择一个 gender_title 项
  const randomGender = data[Math.floor(Math.random() * data.length)];

  // 随机选择该 gender_title 项中的一个 item
  const randomItem =
    randomGender.item[Math.floor(Math.random() * randomGender.item.length)];

  return randomItem;
};

const closeModal = () => {
  dialog.value.closeModal();
};

// 保存
const upgradePackage = () => {
  if (!isRandom.value && selectVoices.value.length == 0) {
    // 未选择声音, 默认开启随机
    isRandom.value = true;
    message.warning("未选择声音, 默认开启随机");
  }

  // 修改收集的选项
  state.selectVoice = JSON.parse(JSON.stringify(selectVoices.value));

  if (isRandom.value) {
    // 从当前列表 随机一个 音色id出来
    const renderItem = getRandomItem(voiceData.list);
    state.tone_id = renderItem.timbre_id;
  } else {
    // 从选择的项中随机一个出来
    state.tone_id =
      selectVoices.value[
        Math.floor(Math.random() * selectVoices.value.length)
      ].tone_id;
  }

  setStore(state);
  // 修改是否随机选项
  store.commit("MODIFY_GLOBALTTSCONFIG_RANDOM", isRandom.value);
  closeModal();
};
// 取消
const cancel = () => {
  closeModal();
};

defineExpose({
  showModal,
  closeModal,
});
</script>

<template>
  <div class="AudioSelection">
    <baseModel
      ref="dialog"
      :contentWidth="'1154px'"
      minWidth="1154px"
      :zIndex="9999"
      :getContainer="() => document.queryselector('.AudioSelection')"
    >
      <!-- minWidth='1140px' -->

      <template #title>
        <div class="title_box"><span>声音</span></div>
      </template>
      <template #content>
        <div class="content">
          <div class="tabs">
            <a-tabs v-model:activeKey="activeKey" @change="tabsChange">
              <a-tab-pane
                v-for="i in voiceData.category"
                :key="i.key"
                :tab="i.value"
              >
                <!-- 声音 卡片 -->
                <div
                  class="voice_cart_content"
                  v-for="(v1, index) in voiceData.list"
                  :key="v1.id"
                >
                  <div class="voice">
                    <span class="voice_cart_title">{{ v1.gender_title }}</span>
                    <div class="voice_cart_list">
                      <div
                        v-for="(v2, index2) in v1.item"
                        :key="index2"
                        class="voice_cart"
                        :class="{
                          active_voice_cart: isSelect(v2) && !isRandom,
                          random_open: isRandom,
                        }"
                        @click="selectCart(v2)"
                      >
                        <div class="voice_left">
                          <div class="imgBox">
                            <img :src="v2.img" alt="" />
                            <div
                              class="play_or_stop"
                              @click.stop="playVoice(v2)"
                            >
                              <PauseOutlined v-if="playState(v2.id)" />
                              <CaretRightOutlined v-else />
                            </div>
                          </div>
                          <div class="described">
                            <span>{{ v2.name }}</span>
                            <span>{{ v2.human_style }}</span>
                          </div>
                        </div>
                      </div>
                    </div>
                    <!-- <a-empty v-else style="height: 240px" /> -->
                  </div>
                </div>
              </a-tab-pane>
            </a-tabs>
          </div>
          <!-- 声音配置 -->
          <div class="voice_config">
            <div class="title_config_box">
              <h2 class="config_title">全局音色配置</h2>
              <!-- 重置按钮 -->
              <span
                :style="{ opacity: resetShow ? 0 : 1 }"
                class="reset_btn"
                @click="resetState"
              >
                <RedoOutlined />
              </span>
            </div>
            <div class="random_sound">
              <span>随机声音</span>
              <a-tooltip
                placement="bottom"
                :getPopupContainer="
                  (triggerNode) => triggerNode.closest('.random_sound')
                "
              >
                <template #title>
                  <span>生成的所有视频组合，将随机使用一个声音效果</span>
                </template>
                <question-circle-outlined
                  style="cursor: pointer; font-size: 14px"
                />
              </a-tooltip>
              <a-switch
                checked-children="开"
                un-checked-children="关"
                v-model:checked="isRandom"
              />
            </div>

            <div class="config_cart">
              <span>音量 {{ state.volume }}</span>
              <div class="slider_box">
                <span style="margin-right: 8px">1</span>
                <a-slider
                  class="slider"
                  :min="1"
                  :max="10"
                  id="test"
                  :step="1"
                  v-model:value="state.volume"
                />
                <span style="margin-left: 8px">10</span>
              </div>
            </div>
            <div class="config_cart">
              <span>语速 {{ state.speed }}</span>
              <div class="slider_box">
                <span style="margin-right: 8px">-2×</span>
                <a-slider
                  class="slider"
                  :min="-2"
                  :max="2"
                  id="test"
                  :step="0.1"
                  v-model:value="state.speed"
                />
                <span style="margin-left: 8px">2×</span>
              </div>
            </div>
            <div class="config_cart">
              <span>情感 {{ state.emotion_intensity }}</span>
              <div class="slider_box">
                <span style="margin-right: 8px">50</span>
                <a-slider
                  class="slider"
                  :min="50"
                  :max="200"
                  id="test"
                  :step="1"
                  v-model:value="state.emotion_intensity"
                />
                <span style="margin-left: 8px">200</span>
              </div>
            </div>
            <div
              class="config_cart"
              v-show="activeKey == 'polyaffective' && toneList.length > 1"
            >
              <span style="margin-right: 10px">语气 </span>
              <a-select
                size="small"
                style="width: 160px; margin-right: 30px"
                :getPopupContainer="
                  (triggerNode) => {
                    return triggerNode.closest('.voice_config');
                  }
                "
                ref="select"
                v-model:value="state.emotion_category"
              >
                <a-select-option
                  v-for="item in toneList"
                  :value="item.key"
                  :key="item.key"
                >
                  {{ item.value }}
                </a-select-option>
              </a-select>
            </div>
            <!-- 文案试听 -->
            <div class="audition_box">
              <div
                style="
                  font-size: 14px;
                  color: #0c0d0e;
                  padding-bottom: 5px;
                  border-bottom: 1px solid #e8e8e8;
                "
              >
                <div
                  style="
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                  "
                >
                  <span>音色试听</span>
                  <a-button
                    v-show="voiceUrl"
                    type="link"
                    style="padding: 0"
                    @click="resetAudition"
                    >重置</a-button
                  >
                </div>
              </div>
              <a-textarea
                :bordered="false"
                v-model:value="audition"
                :autoSize="{ minRows: 3, maxRows: 5 }"
                :maxlength="40"
                placeholder="请输入文案，选择一个音色,点击播放开始试听"
              >
              </a-textarea>

              <div class="bottom_box">
                <a-button
                  :loading="btnLoding"
                  :disabled="isRandom || !selectVoices.length"
                  @click="auditionPlay"
                  type="primary"
                  style="height: 28px; font-size: 13px; margin-top: 20px"
                  class="audition_btn"
                >
                  {{ globalPlay ? "暂停" : "播放" }}
                </a-button>
                <span class="show_count">{{ audition.length }} / 40</span>
              </div>
            </div>
          </div>
        </div>
      </template>
      <template #footer>
        <div class="bottom">
          <a-button
            class="btn"
            key="back"
            @click="cancel"
            style="margin-right: 10px"
            >取消</a-button
          >
          <a-button
            class="btn"
            key="submit"
            type="primary"
            :loading="loading"
            :disabled="disableSubmit"
            @click="upgradePackage"
            >保存</a-button
          >
        </div>
      </template>
    </baseModel>

    <!-- 每个音频的试听audio节点 -->
    <audio
      @ended="handleAudioEnded"
      ref="audioRef"
      :src="voiceUrl"
      style="display: none"
    ></audio>
    <!-- 预览自定义音色的音频节点 -->
    <audio
      @ended="handleGlobalAudioEnded"
      ref="globalAudio"
      :src="globalAudioUrl"
      style="display: none"
    ></audio>
  </div>

  <auditionDialog
    ref="auditionDialogRef"
    @update="updateAudition"
  ></auditionDialog>
</template>

<style lang="less" scoped>
.AudioSelection {
  height: 100%;
}

.title_box {
  span {
    font-size: 18px;
    color: #0c0d0e;
  }
}

.content {
  display: flex;

  .tabs {
    flex: 1;

    .voice_cart_content {
      // height: 100%;
      max-height: 550px;
      overflow-y: auto;

      &:hover {
        &::-webkit-scrollbar {
          display: block;
        }

        // padding-right: 0;
      }

      &::-webkit-scrollbar {
        width: 10px;
        /* 滚动条的宽度 */
        height: 10px;
        /* 滚动条的高度，垂直滚动条可能用得上 */
        display: none;
      }

      &::-webkit-scrollbar-thumb {
        background: #888;
        /* 滑块的背景颜色 */
        border-radius: 10px;
        /* 滑块的圆角 */
      }

      .voice {
        display: flex;
        flex-direction: column;

        .voice_cart_title {
          margin-bottom: 10px;
          font-size: 15px;
          font-weight: 600;
        }

        .voice_cart_list {
          display: flex;
          flex-wrap: wrap;

          :deep(.ant-popover-title) {
            display: none;
          }

          // 省略号编辑按钮
          .info-rg-more {
            cursor: pointer;
            font-size: 20px;
            padding: 1px 6px;
            border-radius: 3px;
            overflow: hidden;
            position: absolute;
            right: 10px;
            top: 10px;
            z-index: 999;

            &:hover {
              background-color: #0000002c;
            }
          }

          // 内部编辑的内容
          .item_config_change {
            display: flex;
            flex-direction: column;
            align-items: center;

            .is_self_parameter {
              width: 100%;
              display: flex;
              align-items: center;
              justify-content: flex-start;
              margin-bottom: 15px;

              span {
                margin-right: 6px;
              }
            }

            .config_tag {
              align-self: flex-end;
              margin-right: 0;
              cursor: pointer;
            }

            .config_cart {
              width: 150px;
              margin-top: 15px;

              &:nth-child(2) {
                margin-top: 0;
              }

              .slider_box {
                display: flex;
                align-items: center;

                span {
                  font-size: 12px;
                  color: #727477;
                }

                .slider {
                  flex: 1;
                }
              }
            }
          }

          .voice_cart {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px 16px;
            width: 200px;
            min-height: 80px;
            border: 1px solid #e5e5e5;
            border-radius: 8px;
            cursor: pointer;
            margin-bottom: 15px;
            margin-right: 25px;
            position: relative;
            background-color: #fff;

            &:hover {
              background-color: #f9f9f9;

              .play_or_stop {
                opacity: 1 !important;
              }
            }

            &.active_voice_cart {
              border-color: #1664ff;
              background-color: #e8f4ff;
            }

            // 开启随机后的样式
            &.random_open {
              filter: grayscale(35%);
              opacity: 0.8;
            }

            .voice_left {
              display: flex;
              align-items: center;

              .described {
                display: flex;
                flex-direction: column;
              }

              .imgBox {
                position: relative;
                border-radius: 30px;
                overflow: hidden;
                margin-right: 20px;

                img {
                  width: 32px;
                }

                .play_or_stop {
                  position: absolute;
                  left: 0;
                  top: 0;
                  z-index: 1;
                  height: 100%;
                  width: 100%;
                  background-color: #b6b6b685;
                  text-align: center;
                  line-height: 32px;
                  font-size: 18px;
                  opacity: 0;
                  transition: opacity 0.3s;
                }
              }
            }
          }
        }
      }
    }
  }

  // 音色配置
  .voice_config {
    width: 330px;
    margin-top: 45px;
    border-top: 1px solid #f0f0f0;
    padding: 0 34px 0 55px;
    position: relative;

    .random_sound {
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      margin-top: 32px;

      span {
        margin-right: 6px;
        font-size: 14px;
      }
    }

    .title_config_box {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding-top: 17px;

      .reset_btn {
        transition: opacity 0.3s;
        cursor: pointer;
        font-size: 16px;
      }

      .config_title {
        font-size: 15px;
        font-weight: 800;
        margin: 0;
      }
    }

    // 文案试听
    .audition_box {
      border: 1px solid #e5e5e5;
      padding: 10px;
      padding-bottom: 40px;
      // padding-left: 20px;
      position: relative;
      // height: 170px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;

      .bottom_box {
        margin-top: 10px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        .audition_btn {
          position: absolute;
          left: 21px;
          bottom: 10px;
        }

        .show_count {
          position: absolute;
          right: 21px;
          bottom: 10px;
        }
      }
    }

    .config_cart {
      margin-top: 32px;

      .slider_box {
        display: flex;
        align-items: center;

        span {
          font-size: 12px;
          color: #727477;
        }

        .slider {
          flex: 1;
        }
      }
    }

    .audition_box {
      margin-top: 32px;
    }
  }
}

.bottom {
  // display: flex;
  // justify-content: center;
  // align-items: center;

  // .btn {
  //     border-radius: 4px;
  //     overflow: hidden;
  // }
}
</style>
